#pragma once

#include <AVUIVisual3DCollection.h>
#include <AVUIFrameworkElement.h>
#include <AVUIIAddChild.h>

namespace AVUI {

class Camera;
class Visual3D;

/// <summary>Provides a rendering surface for 3-D visual content. </summary>
class Viewport3D : public FrameworkElement, public IAddChild
{
    friend class Visual;
public:
    DECLARE_ELEMENT(Viewport3D, FrameworkElement);

#pragma region Public Methods

    /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Controls.Viewport3D" /> class.</summary>
    Viewport3D();

#pragma endregion Public Methods

#pragma region Public Properties

    /// <summary>Gets or sets a camera object that projects the 3-D contents of the <see cref="T:System.Windows.Controls.Viewport3D" /> to the 2-D surface of the <see cref="T:System.Windows.Controls.Viewport3D" />. This is a dependency property. </summary>
    /// <returns>The camera that projects the 3-D contents to the 2-D surface.</returns>
    TRefCountedPtr<Camera> get_Camera() { return (Camera*)(Object*)GetValue(get_CameraProperty()); }
    void set_Camera(Camera* pValue) { SetValue(get_CameraProperty(), (Object*)pValue); } 
    DECLARE_DEPENDENCY_PROPERTY(Camera);

    /// <summary>Gets a collection of the <see cref="T:System.Windows.Media.Media3D.Visual3D" /> children of the <see cref="T:System.Windows.Controls.Viewport3D" />. This is a dependency property. </summary>
    /// <returns>A collection of the <see cref="T:System.Windows.Media.Media3D.Visual3D" /> children of the <see cref="T:System.Windows.Controls.Viewport3D" />.</returns>
    Visual3DCollection* get_Children() { return (Visual3DCollection*) GetValue(get_ChildrenProperty()).get_Ptr(); }
    DECLARE_READONLY_DEPENDENCY_PROPERTY_BEGIN(Children);
        DECLARE_ATTRIBUTE_CONTENTPROPERTY()
    DECLARE_READONLY_DEPENDENCY_PROPERTY_END()

#pragma endregion Public Properties

protected:

#pragma region Protected Methods

    /// <summary>Causes the <see cref="T:System.Windows.Controls.Viewport3D" /> to arrange its visual content to fit a specified size. </summary>
    /// <returns>The final size of the arranged <see cref="T:System.Windows.Controls.Viewport3D" />.</returns>
    /// <param name="finalSize">Size that <see cref="T:System.Windows.Controls.Viewport3D" /> will assume.</param>
    virtual Size ArrangeOverride(const Size& finalSize) AVUI_OVERRIDE;

    /// <summary>Gets the <see cref="T:System.Windows.Media.Visual" /> at a specified position in the <see cref="P:System.Windows.Controls.Viewport3D.Children" /> collection of the <see cref="T:System.Windows.Controls.Viewport3D" />.</summary>
    /// <returns>Visual at the specified position in the <see cref="P:System.Windows.Controls.Viewport3D.Children" /> collection.</returns>
    /// <param name="index">Position of the element in the collection.</param>
    virtual Visual* GetVisualChild(int index) AVUI_OVERRIDE;

#pragma endregion Protected Methods

#pragma region Protected Properties

    /// <summary>Gets an integer that represents the number of <see cref="T:System.Windows.Media.Visual" /> objects in the <see cref="P:System.Windows.Media.Media3D.ModelVisual3D.Children" /> collection of the <see cref="T:System.Windows.Media.Media3D.Visual3D" />.</summary>
    /// <returns>Integer that represents the number of Visuals in the Children collection of the <see cref="T:System.Windows.Media.Media3D.Visual3D" />.</returns>
    virtual int get_VisualChildrenCount() AVUI_OVERRIDE { return 1; }

#pragma endregion Protected Properties

#pragma region IAddChild Methods

    /// <summary>This member supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code.</summary>
    /// <param name="value" />
    void AddChild(Object* pValue);

    /// <summary>This member supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code.</summary>
    /// <param name="text" />
    void AddText(String* pText);

#pragma endregion IAddChild Methods

private:

#pragma region Private Methods
    static void StaticConstructor();
    static void OnCameraChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);
#pragma endregion Private Methods

#pragma region Private Fields
    TRefCountedPtr<Viewport3DVisual> m_pViewport3DVisual;
#pragma endregion Private Fields
};


}; // namespace AVUI
